
#include "lib_mpp.h"

//****************************************************************

static  RKMPPCodecContext g_mpp_ctx;


static pthread_t  pMpp_decode_thread;
static pthread_t  pMpp_timer_thread;

static int        avpacket_index = 0;

static double     mpp_video_clock 	= 0;
static int        mpp_decode_flag   = 1;
static long	      mpp_delay_time    = 33;

//****************************************************************

int mpp_para_deinit(void)
{
	avpacket_index  =  0;
	mpp_decode_flag =  1;
	mpp_delay_time  = 33;

	return 0;
}

//****************************************************************

int mpp_decode_h264(uint8_t *temp_data,int size)
{
	int mode	  = 0;
	int spsLength = 0;
	int ppsLength = 0;
	int nalLength = 0;
	
	uint8_t* ex = NULL;
	uint8_t*  first_packet_buff = NULL;
	uint64_t  first_packet_len	= 0;

	AVPacket tmpPacket;

	if(!temp_data)
		return -1;
	
	if(!size)
		return -1;


	RKMPPCodecContext *mpp_ctx = &g_mpp_ctx;

	uint8_t  startCode[4]	= { 0x00, 0x00, 0x00, 0x01};

	if(memcmp(startCode, temp_data, 4) != 0)
	{		
		if(mode != 2){
			mode = 2;log_d(" avc\n");
		}
		if(avpacket_index == 0)
		{
			avpacket_index = 1;

			log_i("decode first packet,size=%d\n",size);

			ffmpeg_get_extradata(&ex);

			log_i("ex=%x\n",ex);
			if(ex){
				spsLength = (ex[6] << 8) | ex[7];
				// x[8+spsLength]表示PPS个数，通常为1，这里就省略判断处理
				// 取接下来两位作为PPS长度
				ppsLength = (ex[8 + spsLength + 1] << 8) | ex[8 + spsLength + 2];
	
				log_d("spsLength=%d\n",spsLength+4);
				log_d("ppsLength=%d\n",ppsLength+4);

				first_packet_len = spsLength + ppsLength + size + 8;
	
				first_packet_buff = malloc(first_packet_len);
				if(first_packet_buff){
					memset(first_packet_buff,0,first_packet_len);
				}

				memcpy(first_packet_buff, startCode, 4);
				memcpy(first_packet_buff+4,  ex + 8, spsLength);
	
				memcpy(first_packet_buff+4+spsLength, startCode, 4);
				memcpy(first_packet_buff+4+spsLength+4, ex + 8 + spsLength + 2 + 1, ppsLength);
	
				memcpy(first_packet_buff+spsLength+ppsLength+8, temp_data, size);
				
				log_d("\n");
			}

			uint8_t* data = temp_data;
			while (data < temp_data + size) // _avPacket->data中可能有多个NALU，循环处理
			{
				// 取前4字节作为nal的长度
				nalLength = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
				if (nalLength > 0) {
					memcpy(data, startCode, 4); 	// 拼起始码
					//tmpPacket = *(avPacket);		// 仅为了复制packet的其他信息，保存文件可忽略
					//tmpPacket.data = data;			// 把tmpPkt指针偏移到实际数据位置
					//tmpPacket.size = nalLength + 4; // 长度为nal长度+起始码4
			
					//TODO: 处理这个NALU的数据，可以直接把tmpPacket.data写入文件
			
				}
				data = data + 4 + nalLength; // 处理data中下一个NALU数据
			}

			memcpy(first_packet_buff+4+spsLength+4+ppsLength, temp_data, size);

			temp_data = first_packet_buff;
			size = first_packet_len;
				
			//mpp_ctx->avpkt = avPacket;
			log_d("\n");

			decode_one_pkt(mpp_ctx,temp_data,size);
			log_d("\n");

			#if 1
			if(first_packet_buff){
				free(first_packet_buff);
				first_packet_buff = NULL;
			}
			#endif
		}
		else
		{
			log_d("\n");

			uint8_t* data = temp_data;
			while (data < temp_data + size) // _avPacket->data中可能有多个NALU，循环处理
			{
				// 取前4字节作为nal的长度
				log_d("\n");
				nalLength = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
				log_d("nalLength=%d\n",nalLength);
				if (nalLength > 0) {
					memcpy(data, startCode, 4); 	// 拼起始码
					log_d("\n");
					//tmpPacket = *(avPacket);		// 仅为了复制packet的其他信息，保存文件可忽略
					//tmpPacket.data = data;			// 把tmpPkt指针偏移到实际数据位置
					//tmpPacket.size = nalLength + 4; // 长度为nal长度+起始码4
			
					//TODO: 处理这个NALU的数据，可以直接把tmpPacket.data写入文件
			
				}
				log_d("\n");
				data = data + 4 + nalLength; // 处理data中下一个NALU数据
				
				log_d("\n");
			}
			
			log_d("\n");
			//mpp_ctx->avpkt = avPacket;
			decode_one_pkt(mpp_ctx,temp_data,size);
			log_d("\n");
		}
	}
	else
	{
		if(mode != 1){
			mode = 1;log_d(" h264\n");
		}
		
		//mpp_ctx->avpkt = avPacket;
		decode_one_pkt(mpp_ctx,temp_data,size);
	}	

	return 0;
}
void* mpp_timer_task(void *arg)
{

	struct timeval timer;	

	while(1)
	{
		usleep(1000);

		if(!ffmpeg_get_decode_flag()){
			mpp_decode_flag = 0;
			continue;
		}

		if(!mpp_delay_time)
			continue;

		timer.tv_sec  = mpp_delay_time/1000/1000;
		timer.tv_usec = mpp_delay_time;

		//log_i("mpp_delay_time=%d\n",mpp_delay_time);
		//log_i("timer.tv_sec =%d\n",timer.tv_sec);
		//log_i("timer.tv_usec=%d\n",timer.tv_usec);

		switch(select(0, NULL, NULL, NULL, &timer)) {
		case -1:  // 错误
			log_e("Error!\n");
			break;
		case 0: //超时
			//log_e("timeout!\n");
			break;
		default:
			break;
		}

		mpp_decode_flag = 1;
	}
}

//****************************************************************
int mpp_video_sync_clock(int64_t pts,int64_t dts)
{
	int64_t 	delay_time  = 0;
	double      frame_delay = 0;
	AVRational  avrational_audio;

	if(!pts)
		return -1;

	avrational_audio.num = 0;
	avrational_audio.den = 0;

	ffmpeg_get_audio_time_base(&avrational_audio.num,&avrational_audio.den);
	
    mpp_video_clock    = av_q2d(avrational_audio)*pts;
    mpp_video_clock    = av_q2d(avrational_audio)*dts;

	//log_i("video clock = %f,pts=%lld\n",mpp_video_clock,pts);
	log_i("video clock = %f,pts=%lld\n",mpp_video_clock,dts);

#if 0
	alsa_get_audio_clock(&frame_delay);

	if(mpp_video_clock > frame_delay)
	{
		frame_delay = mpp_video_clock - frame_delay;
		delay_time  = frame_delay;
		usleep(delay_time*1000*1000);
	}
	else
	{

	
	}
#endif


	return 0;	
}

int mpp_get_video_clock(double *clock)
{
	*clock = mpp_video_clock;

	return 0;
}
//****************************************************************
void* mpp_decode_thread(void *arg)
{
	int       fps = 0;
	int       packet_size = 0;
	uint8_t * packet_data = NULL;
	int64_t   packet_pts  = 0;
	int64_t   packet_dts  = 0;

	long      us_start    = 0;
	long      us_end      = 0;
	long      fps_time    = 0;
	long      decode_time = 0;

	while(1)
	{
		usleep(1000);
		if(!ffmpeg_get_decode_flag()){
			continue;
		}
		
		if(!ffmpeg_packet_is_ready()){
			continue;
		}

		if(!mpp_decode_flag){
			continue;
		}

		mpp_decode_flag =  0;

		//***************************************************************

		us_start = platform_get_microsecond();
		
		//video_mutex_lock();

		queue_packet_read_video(&packet_data,&packet_size,&packet_pts,&packet_dts);

		mpp_decode_h264(packet_data,packet_size);

		queue_packet_read_free();

		//video_mutex_unlock();
		
		us_end = platform_get_microsecond();

		decode_time = us_end - us_start;
		//***************************************************************

		ffmpeg_get_fps(&fps);

		if(!video_para_get_detime())
		{
			fps_time   = 1*1000*1000/(fps);
		}
		else
		{
			fps_time   = 1*1000*1000/video_para_get_detime();
		}
		//***************************************************************
		if(fps_time > decode_time)
		{
			mpp_delay_time = fps_time - decode_time;
			if(mpp_delay_time >= fps_time)
			{
				mpp_delay_time = fps_time;
			}		
		}
		else{
			mpp_delay_time = 6000;
		}

		//***************************************************************
		//log_i("time=%ld\n",mpp_delay_time);
		//***************************************************************		
	}
}



//****************************************************************

int lib_mpp_init(void)
{	
	int ret = -1;

	log_i("lib mpp init.\n");

    rkmpp_decoder_init(&g_mpp_ctx);

	ret=pthread_create(&pMpp_decode_thread,NULL,mpp_decode_thread,NULL);
	if(ret != 0){
		log_e("thread error=%s\n",strerror(ret));
	}

	ret=pthread_create(&pMpp_timer_thread, NULL, mpp_timer_task, NULL);
	if(ret != 0){
		log_e("thread error=%s\n",strerror(ret));
	}


	return 0;
}


int lib_mpp_deinit(void)
{
	log_i("lib mpp exit.\n");






	return 0;
}


